using Microsoft.Extensions.DependencyInjection;
using Orleans;
using Orleans.Configuration;
using Orleans.Hosting;
using System;

namespace Gasgoo.ShareLibrary.Framework.iQueueProvider
{
    public interface IStreamConfigurator : INamedServiceConfigurator { }

    public static class MemoryStreamConfiguratorExtensions
    {
        public static void ConfigurePartitioning(this IStreamConfigurator configurator, int numOfQueues = HashRingStreamQueueMapperOptions.DEFAULT_NUM_QUEUES)
        {
            configurator.Configure<HashRingStreamQueueMapperOptions>(ob => ob.Configure(options => options.TotalQueueCount = numOfQueues));
        }

        public static void ConfigureCache(this IStreamConfigurator configurator, int cacheSize = SimpleQueueCacheOptions.DEFAULT_CACHE_SIZE)
        {
            configurator.Configure<SimpleQueueCacheOptions>(ob => ob.Configure(options => options.CacheSize = cacheSize));
        }
    }

    public interface IGasgooStreamConfigurator : IStreamConfigurator, ISiloRecoverableStreamConfigurator { }

    public class GasgooServiceStreamConfigurator<TAdapter> : SiloRecoverableStreamConfigurator, IGasgooStreamConfigurator where TAdapter : IAdapterFactory, new()
    {
        public GasgooServiceStreamConfigurator(
            string name, Action<Action<IServiceCollection>> configureServicesDelegate)
            : base(name, configureServicesDelegate, new TAdapter().Create)
        {
            this.ConfigureDelegate(services =>
            {
                services.ConfigureNamedOptionForLogging<HashRingStreamQueueMapperOptions>(name);
            });
        }
    }

    public interface IClusterClientMStreamConfigurator : IMemoryStreamConfigurator, IClusterClientPersistentStreamConfigurator { }

    public class GasgooClientStreamConfigurator<TAdapter> : ClusterClientPersistentStreamConfigurator, IClusterClientMStreamConfigurator
          where TAdapter : IAdapterFactory, new()
    {
        public GasgooClientStreamConfigurator(string name, IClientBuilder builder)
         : base(name, builder, new TAdapter().Create)
        {
        }
    }
}
